/*
 * TcpClient.h
 *
 *   Created on: 2010-03-28
 *  Description: 通用的Client类
 *    Copyright: 2010 @ ICT Li Heyuan
 */

#ifndef CLIENT_H_
#define CLIENT_H_

#include "../net/Network.h"
#include "../json_cpp/value.h"
#include "../../include/crypto/RSATools.h"
#include "../../include/crypto/AESTools.h"
using Json::Value;

#include <string>
using std::string;

class Client
{
public:

	/* 无server地址信息初始化，可以稍后使用setAddr进行初始化
	 *
	 */
	Client() :
		_aes("1234567890543210")
	{
	}

	/* 使用EasyAddr初始化Client
	 * @param addr 服务器的地址
	 */
	Client(const EasyAddr &addr) :
		_serverAddr(addr), _aes("1234567890543210")//@TODO
	{
	}

	/* 使用ip:port初始化Client
	 * @param ip 服务器的ip
	 * @param port 服务器的port
	 */
	Client(const std::string&ip, unsigned int port) :
		_aes("1234567890543210")//@TODO
	{
		_serverAddr.ip = ip;
		_serverAddr.port = port;

		//默认不加密
		_isEncrypt = false;
	}

	/* 析构函数，什么也不做
	 */
	virtual ~Client()
	{

	}

	/* 设置server的地址信息
	 * @param addr server的地址信息
	 */
	void setServerAddr(const EasyAddr &addr)
	{
		_serverAddr = addr;
	}

	/* 设置server的ip:port信息
	 * @param ip server的ip
	 * @param port server的port
	 */
	void setServerAddr(const std::string&ip, unsigned int port)
	{
		_serverAddr.ip = ip;
		_serverAddr.port = port;
	}

	/* 调用_call前预处理（加密、文件等）
	 * @param needResp 如果设为true有response;如果是notification（无须返回），清设置为false
	 */
	bool call(std::string method, Value &param, Value &ret,
			unsigned int timeout = 3);

	/* 调用_notification前预处理（加密、文件等）
	 * @param needResp 如果设为true有response;如果是notification（无须返回），清设置为false
	 */
	bool notification(std::string method, Value &param, unsigned int timeout =
			3);

	/* 是否需要加密（RSA＋AES）
	 * @param true需要,false不需要
	 */
	void setEncrypt(bool en);

protected:
	/* 基于不用传输协议，调用server上的rpc方法，纯虚函数
	 * @param sendBuf json-rpc串
	 * @param ret rpc方法的返回值，成功为result，失败为error
	 * @param timeout 超时时间，秒为单位，默认为3秒
	 */
	virtual bool _call(const string &sendBuf, Json::Value &ret,
			unsigned int timeout = 3) = 0;

	/* 基于不同传输协议，调用server上的notification（无返回），纯虚函数
	 * @param sendBuf json-rpc串
	 * @param timeout 超时时间，秒为单位，默认为3秒
	 */
	virtual bool
	_notification(const string &sendBuf, unsigned int timeout = 3) = 0;

	/* 1.访问Server获取RSA公钥
	 * 2.生成AES私钥
	 * 3.将'params'用AES加密、将AES－Key和AES－IV用RSA公钥加密一起写入callParam
	 * 3.声称json-rpc请求字符串
	 * @param error 出错信息
	 * @param true为call,false为notification
	 * @return 均成功返回true，否则false
	 */
	bool autoEncrypt(std::string method, Value &param, string &jsonReq,
			string &error, bool response = true);

	/* 1.使用AES对称秘钥解密result
	 *
	 */
	bool autoDecrypt(Value &ret, string &error);

protected:
	//server的地址信息
	EasyAddr _serverAddr;

	//是否需要加密
	bool _isEncrypt;

	//RSA公钥匙
	RSATools _rsa;

	//AES对称秘钥
	AESTools _aes;
};

#endif /* CLIENT_H_ */
